#include "FirstService.h"
#include "thrift/async/TAsyncChannel.h"

namespace thrift { namespace test {

FirstService_testString_args::~FirstService_testString_args() noexcept
{
}

uint32_t FirstService_testString_args::read(::apache::thrift::protocol::TProtocol* iprot)
{
    ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot);
    uint32_t xfer = 0;
    std::string fname;
    ::apache::thrift::protocol::TType ftype;
    int16_t fid;

    xfer += iprot->readStructBegin(fname);

    using ::apache::thrift::protocol::TProtocolException;

    while (true)
    {
        xfer += iprot->readFieldBegin(fname, ftype, fid);
        if (ftype == ::apache::thrift::protocol::T_STOP)
        {
            break;
        }
        switch (fid)
        {
            case 1:
                if (ftype == ::apache::thrift::protocol::T_STRING)
                {
                    xfer += iprot->readString(this->thing);
                    this->__isset.thing = true;
                }
                else
                {
                    xfer += iprot->skip(ftype);
                }
                break;
            default:
                xfer += iprot->skip(ftype);
                break;
        }
        xfer += iprot->readFieldEnd();
    }

    xfer += iprot->readStructEnd();

    return xfer;
}

uint32_t FirstService_testString_args::write(::apache::thrift::protocol::TProtocol* oprot) const
{
    uint32_t xfer = 0;
    ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot);
    xfer += oprot->writeStructBegin("FirstService_testString_args");

    // 字段开始写: thing
    xfer += oprot->writeFieldBegin("thing", ::apache::thrift::protocol::T_STRING, 1);
    xfer += oprot->writeString(this->thing);
    xfer += oprot->writeFieldEnd();
    // 字段结束写: thing

    xfer += oprot->writeFieldStop();
    xfer += oprot->writeStructEnd();
    return xfer;
}

FirstService_testString_pargs::~FirstService_testString_pargs() noexcept
{
}

uint32_t FirstService_testString_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const
{
    uint32_t xfer = 0;
    ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot);
    xfer += oprot->writeStructBegin("FirstService_testString_pargs");

    // 字段开始写: thing
    xfer += oprot->writeFieldBegin("thing", ::apache::thrift::protocol::T_STRING, 1);
    xfer += oprot->writeString((*(this->thing)));
    xfer += oprot->writeFieldEnd();
    // 字段结束写: thing

    xfer += oprot->writeFieldStop();
    xfer += oprot->writeStructEnd();
    return xfer;
}

FirstService_testString_result::~FirstService_testString_result() noexcept
{
}

uint32_t FirstService_testString_result::read(::apache::thrift::protocol::TProtocol* iprot)
{
    ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot);
    uint32_t xfer = 0;
    std::string fname;
    ::apache::thrift::protocol::TType ftype;
    int16_t fid;

    xfer += iprot->readStructBegin(fname);

    using ::apache::thrift::protocol::TProtocolException;

    while (true)
    {
        xfer += iprot->readFieldBegin(fname, ftype, fid);
        if (ftype == ::apache::thrift::protocol::T_STOP)
        {
            break;
        }
        switch (fid)
        {
            case 0:
                if (ftype == ::apache::thrift::protocol::T_STRING)
                {
                    xfer += iprot->readString(this->success);
                    this->__isset.success = true;
                }
                else
                {
                    xfer += iprot->skip(ftype);
                }
                break;
            default:
                xfer += iprot->skip(ftype);
                break;
        }
        xfer += iprot->readFieldEnd();
    }

    xfer += iprot->readStructEnd();

    return xfer;
}

uint32_t FirstService_testString_result::write(::apache::thrift::protocol::TProtocol* oprot) const
{
    uint32_t xfer = 0;

    xfer += oprot->writeStructBegin("FirstService_testString_result");

    if (this->__isset.success)
    {
        xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_STRING, 0);
        xfer += oprot->writeString(this->success);
        xfer += oprot->writeFieldEnd();
    }
    xfer += oprot->writeFieldStop();
    xfer += oprot->writeStructEnd();
    return xfer;
}

FirstService_testString_presult::~FirstService_testString_presult() noexcept
{
}

uint32_t FirstService_testString_presult::read(::apache::thrift::protocol::TProtocol* iprot)
{
    ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot);
    uint32_t xfer = 0;
    std::string fname;
    ::apache::thrift::protocol::TType ftype;
    int16_t fid;

    xfer += iprot->readStructBegin(fname);

    using ::apache::thrift::protocol::TProtocolException;

    while (true)
    {
        xfer += iprot->readFieldBegin(fname, ftype, fid);
        if (ftype == ::apache::thrift::protocol::T_STOP)
        {
            break;
        }
        switch (fid)
        {
            case 0:
                if (ftype == ::apache::thrift::protocol::T_STRING)
                {
                    xfer += iprot->readString((*(this->success)));
                    this->__isset.success = true;
                }
                else
                {
                    xfer += iprot->skip(ftype);
                }
                break;
            default:
                xfer += iprot->skip(ftype);
                break;
        }
        xfer += iprot->readFieldEnd();
    }

    xfer += iprot->readStructEnd();

    return xfer;
}

uint32_t FirstService_testString_presult::write(::apache::thrift::protocol::TProtocol* oprot) const
{
    uint32_t xfer = 0;
    ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot);
    xfer += oprot->writeStructBegin("FirstService_testString_presult");

    // 字段开始写: success
    xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_STRING, 0);
    xfer += oprot->writeString((*(this->success)));
    xfer += oprot->writeFieldEnd();
    // 字段结束写: success

    xfer += oprot->writeFieldStop();
    xfer += oprot->writeStructEnd();
    return xfer;
}

void FirstServiceClient::testString(std::string& _return, const std::string& thing)
{
    send_testString(thing);
    recv_testString(_return);
}

void FirstServiceClient::send_testString(const std::string& thing)
{
    int32_t cseqid = 0;
    oprot_->writeMessageBegin("testString", ::apache::thrift::protocol::T_CALL, cseqid);

    FirstService_testString_pargs args;
    args.thing = &thing;
    args.write(oprot_);

    oprot_->writeMessageEnd();
    oprot_->getTransport()->writeEnd();
    oprot_->getTransport()->flush();
}

void FirstServiceClient::recv_testString(std::string& _return)
{
    int32_t rseqid = 0;
    std::string fname;
    ::apache::thrift::protocol::TMessageType mtype;

    iprot_->readMessageBegin(fname, mtype, rseqid);
    if (mtype == ::apache::thrift::protocol::T_EXCEPTION)
    {
        ::apache::thrift::TApplicationException x;
        x.read(iprot_);
        iprot_->readMessageEnd();
        iprot_->getTransport()->readEnd();
        throw x;
    }
    if (mtype != ::apache::thrift::protocol::T_REPLY)
    {
        iprot_->skip(::apache::thrift::protocol::T_STRUCT);
        iprot_->readMessageEnd();
        iprot_->getTransport()->readEnd();
    }
    if (fname.compare("testString") != 0) 
    {
        iprot_->skip(::apache::thrift::protocol::T_STRUCT);
        iprot_->readMessageEnd();
        iprot_->getTransport()->readEnd();
    }

    FirstService_testString_presult result;
    result.success = &_return;
    result.read(iprot_);
    iprot_->readMessageEnd();
    iprot_->getTransport()->readEnd();

    if (result.__isset.success)
    {
         // _return pointer has now been filled
        return;
    }
    throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "testString failed: unknown result");
}

// 生成服务端的相关函数
bool FirstServiceProcessor::dispatchCall(::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, const std::string& fname, int32_t seqid, void* callContext)
{
    ProcessMap::iterator pfn;
    pfn = processMap_.find(fname);
    if (pfn == processMap_.end())
    {
        iprot->skip(::apache::thrift::protocol::T_STRUCT);
        iprot->readMessageEnd();
        iprot->getTransport()->readEnd();
        ::apache::thrift::TApplicationException x(::apache::thrift::TApplicationException::UNKNOWN_METHOD, "Invalid method name: '" + fname + "'");
        oprot->writeMessageBegin(fname, ::apache::thrift::protocol::T_EXCEPTION, seqid);
        x.write(oprot);
        oprot->writeMessageEnd();
        oprot->getTransport()->writeEnd();
        oprot->getTransport()->flush();
        return true;
    }

    (this->*(pfn->second))(seqid, iprot, oprot, callContext);

    return true;
}

void FirstServiceProcessor::process_testString(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext)
{
    void* ctx = nullptr;
    if (this->eventHandler_.get() != nullptr)
    {
        ctx = this->eventHandler_->getContext("FirstService.testString", callContext);
    }
    ::apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "FirstService.testString");

    if (this->eventHandler_.get() != nullptr)
    {
        this->eventHandler_->preRead(ctx, "FirstService.testString");
    }

    FirstService_testString_args args;
    args.read(iprot);
    iprot->readMessageEnd();
    uint32_t bytes = iprot->getTransport()->readEnd();

    if (this->eventHandler_.get() != nullptr)
    {
        this->eventHandler_->postRead(ctx, "FirstService.testString", bytes);
    }

    FirstService_testString_result result;
    try
    {
        iface_->testString(result.success, args.thing);
        result.__isset.success = true;
    }
    catch (const std::exception& e)
    {
        if (this->eventHandler_.get() != nullptr)
        {
            this->eventHandler_->handlerError(ctx, "FirstService.testString");
        }

        ::apache::thrift::TApplicationException x(e.what());
        oprot->writeMessageBegin("testString", ::apache::thrift::protocol::T_EXCEPTION, seqid);
        x.write(oprot);
        oprot->writeMessageEnd();
        oprot->getTransport()->writeEnd();
        oprot->getTransport()->flush();
        return;
    }

    if (this->eventHandler_.get() != nullptr)
    {
        this->eventHandler_->preWrite(ctx, "FirstService.testString");
    }

    oprot->writeMessageBegin("testString", ::apache::thrift::protocol::T_REPLY, seqid);
    result.write(oprot);
    oprot->writeMessageEnd();
    bytes = oprot->getTransport()->writeEnd();
    oprot->getTransport()->flush();

    if (this->eventHandler_.get() != nullptr)
    {
        this->eventHandler_->postWrite(ctx, "FirstService.testString", bytes);
    }
}

::std::shared_ptr<::apache::thrift::TProcessor> FirstServiceProcessorFactory::getProcessor(const ::apache::thrift::TConnectionInfo& connInfo)
{
    ::apache::thrift::ReleaseHandler<FirstServiceIfFactory> cleanup(handlerFactory_);
    ::std::shared_ptr<FirstServiceIf> handler(handlerFactory_->getHandler(connInfo), cleanup);
    ::std::shared_ptr<::apache::thrift::TProcessor> processor(new FirstServiceProcessor(handler));
    return processor;
}

void FirstServiceConcurrentClient::testString(std::string& _return, const std::string& thing)
{
    int32_t seqid = send_testString(thing);
    recv_testString(_return, seqid);
}

int32_t FirstServiceConcurrentClient::send_testString(const std::string& thing)
{
    int32_t cseqid = this->sync_->generateSeqId();
    ::apache::thrift::async::TConcurrentSendSentry sentry(this->sync_.get());
    oprot_->writeMessageBegin("testString", ::apache::thrift::protocol::T_CALL, cseqid);

    FirstService_testString_pargs args;
    args.thing = &thing;
    args.write(oprot_);

    oprot_->writeMessageEnd();
    oprot_->getTransport()->writeEnd();
    oprot_->getTransport()->flush();

    sentry.commit();
    return cseqid;
}

void FirstServiceConcurrentClient::recv_testString(std::string& _return, const int32_t seqid)
{
    int32_t rseqid = 0;
    std::string fname;
    ::apache::thrift::protocol::TMessageType mtype;

    // the read mutex gets dropped and reacquired as part of waitForWork()
    // The destructor of this sentry wakes up other clients
    ::apache::thrift::async::TConcurrentRecvSentry sentry(this->sync_.get(), seqid);

    while (true)
    {
        if (!this->sync_->getPending(fname, mtype, rseqid)) 
        {
            iprot_->readMessageBegin(fname, mtype, rseqid);
        }
        if (seqid == rseqid)
        {
            if (mtype == ::apache::thrift::protocol::T_EXCEPTION)
            {
                ::apache::thrift::TApplicationException x;
                x.read(iprot_);
                iprot_->readMessageEnd();
                iprot_->getTransport()->readEnd();
                sentry.commit();
                throw x;
            }
            if (mtype != ::apache::thrift::protocol::T_REPLY)
            {
                iprot_->skip(::apache::thrift::protocol::T_STRUCT);
                iprot_->readMessageEnd();
                iprot_->getTransport()->readEnd();
            }
            if (fname.compare("testString") != 0) 
            {
                iprot_->skip(::apache::thrift::protocol::T_STRUCT);
                iprot_->readMessageEnd();
                iprot_->getTransport()->readEnd();

                // in a bad state, don't commit
                using ::apache::thrift::protocol::TProtocolException;
                throw TProtocolException(TProtocolException::INVALID_DATA);
            }

            FirstService_testString_presult result;
            result.success = &_return;
            result.read(iprot_);
            iprot_->readMessageEnd();
            iprot_->getTransport()->readEnd();

            if (result.__isset.success)
            {
                 // _return pointer has now been filled
                sentry.commit();
                return;
            }
            // in a bad state, don't commit
            throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "testString failed: unknown result");
        }
        // seqid != rseqid
        this->sync_->updatePending(fname, mtype, rseqid);

        // this will temporarily unlock the readMutex, and let other clients get work done
        this->sync_->waitForWork(seqid);
    } // end while(true)
}

void FirstServiceCobClient::testString(::std::function<void(FirstServiceCobClient* client)> cob, const std::string& thing)
{
    send_testString(thing);
    channel_->sendAndRecvMessage(::std::bind(cob, this), otrans_.get(), itrans_.get());
}

void FirstServiceCobClient::send_testString(const std::string& thing)
{
    int32_t cseqid = 0;
    otrans_->resetBuffer();
    oprot_->writeMessageBegin("testString", ::apache::thrift::protocol::T_CALL, cseqid);

    FirstService_testString_pargs args;
    args.thing = &thing;
    args.write(oprot_);

    oprot_->writeMessageEnd();
    oprot_->getTransport()->writeEnd();
    oprot_->getTransport()->flush();
}

void FirstServiceCobClient::recv_testString(std::string& _return)
{
    int32_t rseqid = 0;
    std::string fname;
    ::apache::thrift::protocol::TMessageType mtype;
    bool completed = false;

    try
    {
        iprot_->readMessageBegin(fname, mtype, rseqid);
        if (mtype == ::apache::thrift::protocol::T_EXCEPTION)
        {
            ::apache::thrift::TApplicationException x;
            x.read(iprot_);
            iprot_->readMessageEnd();
            iprot_->getTransport()->readEnd();
            completed = true;
            completed__(true);
            throw x;
        }
        if (mtype != ::apache::thrift::protocol::T_REPLY)
        {
            iprot_->skip(::apache::thrift::protocol::T_STRUCT);
            iprot_->readMessageEnd();
            iprot_->getTransport()->readEnd();
            completed = true;
          completed__(false);
        }
        if (fname.compare("testString") != 0) 
        {
            iprot_->skip(::apache::thrift::protocol::T_STRUCT);
            iprot_->readMessageEnd();
            iprot_->getTransport()->readEnd();
            completed = true;
            completed__(false);
        }

        FirstService_testString_presult result;
        result.success = &_return;
        result.read(iprot_);
        iprot_->readMessageEnd();
        iprot_->getTransport()->readEnd();

        if (result.__isset.success)
        {
             // _return pointer has now been filled
            completed = true;
            completed__(true);
            return;
        }
        completed = true;
        completed__(true);
        throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "testString failed: unknown result");
    }
    catch (...) 
    {
        if (!completed)
        {
            completed__(false);
        }
        throw;
    }
}

// 生成服务端的相关函数
void FirstServiceAsyncProcessor::dispatchCall(::std::function<void(bool ok)> cob, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, const std::string& fname, int32_t seqid)
{
    ProcessMap::iterator pfn;
    pfn = processMap_.find(fname);
    if (pfn == processMap_.end())
    {
        iprot->skip(::apache::thrift::protocol::T_STRUCT);
        iprot->readMessageEnd();
        iprot->getTransport()->readEnd();
        ::apache::thrift::TApplicationException x(::apache::thrift::TApplicationException::UNKNOWN_METHOD, "Invalid method name: '" + fname + "'");
        oprot->writeMessageBegin(fname, ::apache::thrift::protocol::T_EXCEPTION, seqid);
        x.write(oprot);
        oprot->writeMessageEnd();
        oprot->getTransport()->writeEnd();
        oprot->getTransport()->flush();
        return cob(true);
    }

    (this->*(pfn->second))(cob, seqid, iprot, oprot);

    return;
}

void FirstServiceAsyncProcessor::process_testString(::std::function<void(bool ok)> cob, int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot)
{
    FirstService_testString_args args;
    void* ctx = nullptr;
    if (this->eventHandler_.get() != nullptr)
    {
        ctx = this->eventHandler_->getContext("FirstService.testString", nullptr);
    }
    ::apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "FirstService.testString");

    try
    {
        if (this->eventHandler_.get() != nullptr)
        {
            this->eventHandler_->preRead(ctx, "FirstService.testString");
        }
        args.read(iprot);
        iprot->readMessageEnd();
        uint32_t bytes = iprot->getTransport()->readEnd();
        if (this->eventHandler_.get() != nullptr)
        {
            this->eventHandler_->postRead(ctx, "FirstService.testString", bytes);
        }
    }
    catch (const std::exception&)
    {
        if (this->eventHandler_.get() != nullptr)
        {
            this->eventHandler_->handlerError(ctx, "FirstService.testString");
        }
        return cob(false);
    }
    freer.unregister();
    void (FirstServiceAsyncProcessor::*return_fn)(::std::function<void(bool ok)> cob, int32_t seqid, ::apache::thrift::protocol::TProtocol* oprot, void* ctx, const std::string& _return) =
        &FirstServiceAsyncProcessor::return_testString;
    iface_->testString(::std::bind(return_fn, this, cob, seqid, oprot, ctx, ::std::placeholders::_1),
        args.thing);
}

void FirstServiceAsyncProcessor::return_testString(::std::function<void(bool ok)> cob, int32_t seqid, ::apache::thrift::protocol::TProtocol* oprot, void* ctx, const std::string& _return)
{
    FirstService_testString_presult result;
    result.success = const_cast<std::string*>(&_return);
    result.__isset.success = true;

    if (this->eventHandler_.get() != nullptr)
    {
        ctx = this->eventHandler_->getContext("FirstService.testString", nullptr);
    }
    ::apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "FirstService.testString");

    if (this->eventHandler_.get() != nullptr)
    {
        this->eventHandler_->preWrite(ctx, "FirstService.testString");
    }

    oprot->writeMessageBegin("testString", ::apache::thrift::protocol::T_REPLY, seqid);
    result.write(oprot);
    oprot->writeMessageEnd();
    uint32_t bytes = oprot->getTransport()->writeEnd();
    oprot->getTransport()->flush();
    if (this->eventHandler_.get() != nullptr) 
    {
        this->eventHandler_->postWrite(ctx, "FirstService.testString", bytes);
    }
    return cob(true);
}

::std::shared_ptr<::apache::thrift::async::TAsyncProcessor> FirstServiceAsyncProcessorFactory::getProcessor(const ::apache::thrift::TConnectionInfo& connInfo)
{
    ::apache::thrift::ReleaseHandler<FirstServiceCobSvIfFactory> cleanup(handlerFactory_);
    ::std::shared_ptr<FirstServiceCobSvIf> handler(handlerFactory_->getHandler(connInfo), cleanup);
    ::std::shared_ptr<::apache::thrift::async::TAsyncProcessor> processor(new FirstServiceAsyncProcessor(handler));
    return processor;
}

}} // namespace

